package com.hyd.demo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author： hyd
 * @time： 2024/7/18 15:23
 * @name： DefaultThreadPool
 */
public class DefaultThreadPool<Job extends Runnable> implements ThreadPool<Job>{
    //最大线程数
    private static final int MAX_WORKER_NUMBERS = 10;
    //核心线程数
    private static final int DEFAULT_WORKER_NUMBERS = 5;
    //最小线程数
    private static final int MIN_WORKER_NUMBERS = 1;
    //任务队列
    private final LinkedList<Job> jobs = new LinkedList<Job>();
    //线程列表
    private final List<Worker> workers = Collections.synchronizedList(new ArrayList<>());
    //线程数量
    private int workerNumber = DEFAULT_WORKER_NUMBERS;
    //线程编号
    private AtomicLong threadNumber = new AtomicLong();

    public DefaultThreadPool() {
        initializeWokers(workerNumber);
    }

    public DefaultThreadPool(int num) {
        if (num > MAX_WORKER_NUMBERS){
            workerNumber = MAX_WORKER_NUMBERS;
        }else if(num < MIN_WORKER_NUMBERS){
            workerNumber = MIN_WORKER_NUMBERS;
        }else {
            workerNumber = num;
        }
        initializeWokers(workerNumber);
    }

    private void initializeWokers(int workerNumber) {
        for (int i = 0; i < workerNumber; i++) {
            Worker worker = new Worker();
            workers.add(worker);
            Thread thread = new Thread(worker,"ThreadPool-worker-"+threadNumber.incrementAndGet());
            thread.start();
        }
    }

    @Override
    public void execute(Job job) {
        if(job != null){
            synchronized (jobs){
                jobs.add(job);
                jobs.notify();
            }
        }
    }

    @Override
    public void shtdown() {
        for (Worker worker : workers) {
            worker.shutdown();
        }
    }

    @Override
    public void addWorkers(int num) {
        synchronized (jobs){
            if (num + this.workerNumber > MAX_WORKER_NUMBERS){
                num = MAX_WORKER_NUMBERS - this.workerNumber;
            }
            initializeWokers(num);
            this.workerNumber += num;
        }
    }

    @Override
    public void removeWorker(int num) throws IllegalAccessException {
        synchronized (jobs){
            if(num >= this.workerNumber){
                throw  new IllegalAccessException("beyond workNum");
            }
            int count = 0;
            while (count < num){
                Worker worker = workers.get(count);
                if (workers.remove(worker)){
                    worker.shutdown();
                    count++;
                }
            }
            this.workerNumber -= num;
        }
    }

    @Override
    public int getJobSize() {
        return jobs.size();
    }

    public int getWorkerNumber() {
        return workerNumber;
    }

    class Worker implements Runnable{

        private volatile  boolean running = true;

        @Override
        public void run() {
            while (running){
                Job job = null;
                synchronized (jobs){
                    while (jobs.isEmpty()){
                        try{
                            jobs.wait();
                        }catch (InterruptedException e){
                            Thread.currentThread().interrupt();
                            return;
                        }
                    }
                    job = jobs.removeFirst();
                }
                if (job!=null){
                    try{
                        job.run();
                    }catch (Exception e){
                    }
                }
            }
        }
        public void shutdown(){
            running = false;
        }
    }
}
